﻿using UnityEngine;
using LuaInterface;
/// <summary>
/// LuaComponent主要有Get和Add两个静态方法，其中Get相当于UnityEngine中的GetComponent方法，Add相当于AddComponent方法
/// 只不过这里添加的是Lua组件不是C#组件。每个LuaComponent拥有一个LuaTable(lua表)类型的变量Table,它既引用上述的Component表。
/// Add方法使用AddComponent添加LuaComponent，调用参数中lua表的New方法，将其返回的表赋予table.
/// Get方法使用GetComponents获取游戏对象上的所有LuaComponent(一个游戏对象可能包含多个lua组件,有参数table决定需要获取哪一个)，
/// 通过元表地址找到对应LuaComponent，返回lua表
/// </summary>
public class LuaComponent : MonoBehaviour
{
    //lua表
    public LuaTable luaTable;

    /// <summary>
    /// 添加Lua组件
    /// </summary>
    /// <param name="gameObject">对应的对象</param>
    /// <param name="tableClass">对应的lua表对象</param>
    /// <returns></returns>
    public static LuaTable Add(GameObject gameObject,LuaTable tableClass)
    {
        LuaFunction func = tableClass.GetLuaFunction("New");

        if(func == null) return null;
        
        ///
        /// object[] rets = func.call(tableClass);
        /// if(rets.Length != 1)
        ///     return null;
        /// 
        //lua升级后，Call方法不再返回对象，因此改为Invoke方法实现
        object rets = func.Invoke<LuaTable,object>(tableClass);
        if(rets == null) return null;

        LuaComponent luaComponent = gameObject.AddComponent<LuaComponent>();
        luaComponent.luaTable = (LuaTable)(rets);

        luaComponent.CallAwake();
        return luaComponent.luaTable;
    }

    /// <summary>
    /// 添加对应的Lua组件
    /// </summary>
    /// <param name="gameObject">在CS中对应的对象</param>
    /// <param name="tableClass">在Lua中对应的对象表</param>
    /// <param name="args">添加的参数</param>
    /// <returns></returns>
    public static LuaTable Add(GameObject gameObject,LuaTable tableClass,LuaTable args)
    {
        LuaFunction func = tableClass.GetLuaFunction("New");
        if(func == null) return null;

        object rets = func.Invoke<LuaTable,object>(tableClass);
        if(rets == null) return null;

        LuaComponent luaComponent = gameObject.AddComponent<LuaComponent>();
        luaComponent.luaTable = (LuaTable)(rets);

        luaComponent.CallAwake(args);
        return luaComponent.luaTable;
    }

    /// <summary>
    /// 添加Lua组件
    /// </summary>
    /// <param name="gameObject">在CS中对应的对象</param>
    /// <param name="tableClass">在Lua中对应的表对象</param>
    /// <param name="isAllowOneComponent"></param>
    /// <returns></returns>
    public static LuaTable Add(GameObject gameObject,LuaTable tableClass,bool isAllowOneComponent = true)
    {
        //如果已经存在，则不再添加
        LuaComponent luaComponent = gameObject.GetComponent<LuaComponent>();
        if(luaComponent != null && isAllowOneComponent)
        {
            return null;
        }
        LuaFunction func = tableClass.GetLuaFunction("New");
        if(func == null) return null;

        object rets = func.Invoke<LuaTable,object>(tableClass);
        if(rets == null) return null;

        LuaComponent luaComponent2 = gameObject.AddComponent<LuaComponent>();
        luaComponent2.luaTable = (LuaTable)rets;
                
        luaComponent2.CallAwake();
        return luaComponent2.luaTable;
    }

    public static LuaTable Get(GameObject gameObject,LuaTable luaTable)
    {
        LuaComponent luaComponent = gameObject.GetComponent<LuaComponent>();
        string mat1 = luaTable.ToString();
        string mat2 = luaComponent.luaTable.GetMetaTable().ToString();
        if(mat1 == mat2)    return luaComponent.luaTable;

        return null;
    }

    void CallAwake()
    {
        LuaFunction luaFunction = luaTable.GetLuaFunction("Awake");

        if(luaFunction != null)
            luaFunction.Call(luaTable, gameObject);        
    }

    void CallAwake(LuaTable args)
    {
        LuaFunction luaFunction = luaTable.GetLuaFunction("Awake");
        if(luaFunction != null)
            luaFunction.Call(luaTable, gameObject, args);
    }

    private void OnEnable()
    {
        if(luaTable == null)    return;
        LuaFunction luaFunction = luaTable.GetLuaFunction("OnEnable");

        if(luaFunction != null)     luaFunction.Call(luaTable, gameObject);
    }

    void Start()
    {
        LuaFunction luaFunction = luaTable.GetLuaFunction("Start");
        if(luaFunction != null)
            luaFunction.Call(luaTable, gameObject);
    }

    void Updata()
    {
        LuaFunction luaFunction = luaTable.GetLuaFunction("Update");
        if(luaFunction != null)
            luaFunction.Call(luaTable, gameObject);
    }

    private void FixedUpdate() 
    {
        LuaFunction luaFunction = luaTable.GetLuaFunction("FixedUpdate");
        if(luaFunction != null)
            luaFunction.Call(luaTable, gameObject);    
    }

    void OnCollisionEnter(Collision collisionInfo)
    {
        LuaFunction luaFunction = luaTable.GetLuaFunction("OnCollisionEnter");
        if(luaFunction != null)
            luaFunction.Call(luaTable, gameObject);
    }

    /// <summary>
    /// 结束
    /// </summary>
    private void OnDisable() 
    {
        if(luaTable != null)
        {
            LuaFunction luaFunction = luaTable.GetLuaFunction("OnDisable");

            if(luaFunction != null)
            {
                luaFunction.Call(luaTable, gameObject);
            }
        }
    }

    /// <summary>
    /// 销毁
    /// </summary>
    private void OnDestroy()
    {
        if(luaTable != null)
        {
            LuaFunction luaFunction = luaTable.GetLuaFunction("OnDestroy");

            if(luaFunction != null)
                luaFunction.Call(luaTable, gameObject);            
        }
    }
}
